<template>
  <div class="vir-table">
    <el-table-v2 :columns="getColumns" :data="data" :width="width" :height="height">
      <template #empty> 没有查询到符合条件的记录 </template>
    </el-table-v2>
    <div class="batch-oprate" v-if="isAllCheck ? pagingData.total : selectLength">
      <el-checkbox v-if="showIsAllCheckBox" v-model="isAllCheck" @change="checkAllData">全选</el-checkbox>
      <span class="selected-count"
        >已选择<span class="selectedNum">{{ isAllCheck ? pagingData.total : selectLength }}</span
        >项</span
      >
      <div class="selectedBtn" v-for="(item, index) in batchs" v-bind:key="index">
        <el-button link type="primary" :disabled="item.disabled ? item.disabled : false" @click="batchClick(item)">
          {{ item.name }}
          <el-tooltip
            :show-after="500"
            v-if="item.tipContent"
            effect="light"
            :content="item.tipContent"
            placement="top"
          >
            <i class="MC_iconfont MC_icon-yiwen-mian"></i>
          </el-tooltip>
        </el-button>
        <div v-if="index !== batchs.length - 1" class="line"></div>
      </div>
      <span class="V7_iconfont V7_iconV7tubiao_guanbi oprate-close" @click="cancelSelectFun">icon close</span>
    </div>
    <template v-if="showPagination">
      <el-pagination
        class="pages"
        :disabled="isAllCheck"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        :current-page="pagingData.page"
        :page-sizes="[10, 20, 50]"
        :page-size="pagingData.limit"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagingData.total"
      >
      </el-pagination>
    </template>
  </div>
</template>
<script lang="tsx">
import { unref, defineComponent, h, toRefs, computed, reactive, watch, renderSlot, onMounted, nextTick } from 'vue'
import type { FunctionalComponent } from 'vue'
import { ElCheckbox, TableV2FixedDir } from 'element-plus'
import cloneDeep from 'lodash/cloneDeep'
import SearchCheckBox from './search-checkbox/index.vue'
export default defineComponent({
  name: 'VirTable',
  props: {
    data: {
      // 数据
      type: Array,
      default: () => []
    },
    columns: {
      // 表头
      type: Array,
      default: () => []
    },
    pagingData: {
      // 分页
      type: Object,
      default: () => ({
        total: 120,
        limit: 10
      })
    },
    selection: {
      // 是否展示表格前面的多选框
      type: Boolean,
      default: false
    },
    showPagination: {
      // 是否展示翻页，默认展示
      type: Boolean,
      default: true
    },
    showIsAllCheckBox: {
      // 批量操作的全选
      type: Boolean,
      default: true
    },
    headersConfig: {
      // 是否展示配置表头，默认不展示
      type: Boolean,
      default: false
    },
    height: {
      type: Number,
      default: 400
    },
    batchs: {
      // 批量操作
      type: Array,
      default: () => []
    }
  },
  emits: ['onPageChange', 'onPageSizeChange', 'onSelectChange', 'onCheckHeadersChange'],
  setup(props, { emit, slots }) {
    const state = reactive({
      checkList: [], // 表头数据
      isAllCheck: false, // 是否全选
      showLoading: false, // loading...
      pageSelect: {} as any, // 根据选择存储数据
      selectList: [], // 选中数据
      checkInit: false, // 是否初始化
      showColumns: [] as any, // 处理过的并且展示的表头
      width: '' // 表格宽度
    })

    const selectLength: any = computed(() => {
      // 选中的数量
      let length: any = 0
      Object.keys(state.pageSelect).forEach((page) => {
        length += state.pageSelect[page].length
      })
      return length
    })

    const getColumns = computed(() => {
      return props.columns.length && props.columns.filter((item: any) => item.show)
    })

    const cancelSelectFun = () => {
      // 取消选择
      state.pageSelect = {} // 清空当前选择项
      state.isAllCheck = false
      clearSelection() // 取消checked
    }

    const clearSelection = () => {
      // 清空选择
      const _data: any = unref(props.data)
      _data.forEach((item: any) => {
        item.checked = false
      })
    }

    const checkAllData = (data: any) => {
      // 选择全部
      state.isAllCheck = data
      if (data) {
        // 全选
        state.pageSelect[props.pagingData.page] = cloneDeep(props.data) // 存储当页数据
        clearSelection() // 先取消选择
        props.data.forEach((item: any) => {
          // 当前页全选
          item.checked = true // 当前页全选
        })
      } else {
        // 取消全选
        cancelSelectFun()
      }
    }

    const handleCheckChange = (Datalist: any, isInit: any) => {
      // 表头配置变化
      if (state.checkInit && isInit === true) {
        // 是否是初始化
        return
      }
      state.showLoading = true
      setTimeout(() => {
        state.showLoading = false
      }, 400)
      if (isInit === true) {
        state.checkInit = true
      }
      state.checkList = Datalist
      emit('onCheckHeadersChange', Datalist, isInit)
    }

    const init = () => {
      // 初始化表头配置
      state.showColumns = props.columns
      // 自定义表格
      state.showColumns.forEach((item: any) => {
        if (item.custom) {
          // 自定义内容
          item.cellRenderer = ({ rowData }: any) => {
            return renderSlot(slots, item.key, { data: rowData })
          }
        }
        if (item.key === 'oprate') {
          // 操作列
          item.fixed = TableV2FixedDir.RIGHT
          item.cellRenderer = ({ rowData }: any) => {
            return renderSlot(slots, item.key, { data: rowData })
          }
        }
      })

      // 表头配置
      if (props.headersConfig) {
        state.showColumns.push({ width: 50, show: true })
        const headerConfig = state.showColumns[state.showColumns.length - 1]
        headerConfig.fixed = TableV2FixedDir.RIGHT
        headerConfig.headerCellRenderer = () => {
          return <SearchCheckBox data={props.columns} onOnCheckChange={handleCheckChange} />
        }
      }

      // 有筛选框
      if (props.selection) {
        type SelectionCellProps = {
          value: boolean
          intermediate?: boolean
          onChange: any
        }
        const SelectionCell: FunctionalComponent<SelectionCellProps> = ({ value, intermediate = false, onChange }) => {
          return <ElCheckbox onChange={onChange} modelValue={value} indeterminate={intermediate} />
        }
        // 向数据中添加筛选框
        state.showColumns.unshift({
          key: 'selection',
          width: 50,
          show: true,
          cellRenderer: ({ rowData }: any) => {
            //自定义单元格渲染器
            const onChange = (value: boolean) => (rowData.checked = value)
            return <SelectionCell value={rowData.checked} onChange={onChange} />
          },
          headerCellRenderer: () => {
            // 自定义头部渲染器
            const _data: any = unref(props.data)
            const onChange = (value: boolean) =>
              _data.map((row: any) => {
                row.checked = value
                return row
              })
            const allPageSelect = _data.every((row: any) => row.checked)
            const containsChecked = _data.some((row: any) => row.checked)
            state.pageSelect[props.pagingData.page] = _data.filter((row: any) => row.checked)
            return (
              <SelectionCell
                value={allPageSelect}
                intermediate={containsChecked && !allPageSelect}
                onChange={onChange}
              />
            )
          }
        })
      }
    }

    const getWidth = () => {
      nextTick(() => {
        const ele: any = document.getElementsByClassName('vir-table')[0]
        if (ele) {
          state.width = ele.offsetWidth
        }
      })
    }

    onMounted(() => {
      getWidth()
      init()
    })

    const handleCurrentChange = (page: any) => {
      // 翻页
      emit('onPageChange', page)
    }

    const handleSizeChange = (size: any) => {
      // limit变化
      emit('onPageSizeChange', size)
    }

    watch(
      () => state.pageSelect[props.pagingData.page],
      (newVal: any) => {
        emit('onSelectChange', newVal) // 筛选框变化外抛事件
        if (newVal && newVal.length === props.pagingData.total && props.showIsAllCheckBox) {
          state.isAllCheck = true
        }
      }
    )

    return {
      ...toRefs(state),
      handleSizeChange,
      handleCurrentChange,
      checkAllData,
      cancelSelectFun,
      selectLength,
      getColumns
    }
  }
})
</script>
<style lang="stylus" scoped>
.vir-table
  width: 100%
  .MC_icon-zidingyi
    cursor pointer
  .icon-active
    color #008cee
  .batch-oprate
    height 40px
    line-height 40px
    background rgba(30, 99, 245, 0.1)
    border-radius 4px
    display flex
    align-items center
    padding 0 18px 0
    position relative
    .selected-count
      margin 0 24px 0 18px
      color #303753
      .selectedNum
        color var(--mc-main-color)
        margin 0 4px 0
    .selectedBtn
      display flex
      align-items: center
      .line
        width 1px
        height 10px
        margin 0 8px
        background rgba(30, 99, 245, 0.3)
    .oprate-close
      color var(--mc-main-color)
      cursor pointer
      position absolute
      right 18px
  .pages
    display flex
    justify-content flex-end
    height 48px
    align-items center
</style>
